package org.octopus.data.desensitized.fastjson.serializer;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import lombok.extern.slf4j.Slf4j;
import org.octopus.data.desensitized.core.annotation.Desensitized;
import org.octopus.data.desensitized.core.annotation.DesensitizedRule;
import org.octopus.data.desensitized.core.registry.GlobalDesensitizedStrategyRegistry;
import org.octopus.data.desensitized.core.strategy.DesensitizedStrategy;
import org.octopus.data.desensitized.core.util.DesensitizedUtils;

/**
 * @author lemon
 * @date 2021/8/28 08:59
 */
@Slf4j
public class FastJsonDesensitizedSerializer implements ObjectSerializer {

    @Override
    public void write(JSONSerializer jsonSerializer, Object value, Object name, Type type, int i) throws IOException {
        log.info("value = {}, name = {}, type = {}, i = {}", value, name, type, i);

        if (!type.equals(String.class)) {
            return;
        }

        Field field;
        Object object = jsonSerializer.getContext().object;
        Class<?> clazz = object.getClass();

        try {
            field = clazz.getDeclaredField((String) name);
        } catch (Exception e) {
            log.error(String.format("获取对象[%s]上的字段[%s]失败：%s", clazz, name, e.getMessage()), e);
            return;
        }

        // 获取注解
        Desensitized desensitized = field.getAnnotation(Desensitized.class);

        if (desensitized == null) {
            return;
        }

        if (!desensitized.enable()) {
            log.warn("对象[{}]字段[{}]上脱敏注解未启用：{}", clazz, name, desensitized);
            return;
        }

        DesensitizedRule desensitizedRule = DesensitizedUtils.buildDesensitizedRule(desensitized);

        DesensitizedStrategy<String> desensitizedStrategy =
                GlobalDesensitizedStrategyRegistry.obtainDesensitizedStrategy(String.class,
                        desensitized.desensitizedPolicy());

        if (desensitizedStrategy == null) {
            log.warn("对象[{}]字段[{}]未找到匹配的脱敏策略，脱敏注解：{}", clazz, name, desensitized);
            return;
        }

        String newValue = desensitizedStrategy.convert((String) value, desensitizedRule);

        log.info("对象[{}]字段[{}]原始值[{}]脱敏后[{}]", clazz, name, value, newValue);

        jsonSerializer.write(newValue);
    }
}
